{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Factory Methodパターン\n",
    "\n",
    "* ファクトリメソッドとは\n",
    "    * インスタンスの生成をサブクラスに任せるパターン\n",
    "    * クラスの選択をサブクラスに任せる\n",
    "    * インスタンスの生成部分を切り離すことで、結合度を下げて追加・変更・保守を容易にする\n",
    "        * 生成するProductへの依存度が下がる\n",
    "* 構成要素\n",
    "    * Creator\n",
    "        * ConcreteFactoryの共通部分の処理を行う\n",
    "        * ここではInstumentFactory\n",
    "    * ConcreteCreator\n",
    "        * 実際にオブジェクトの生成を行う\n",
    "        * ここではSaxophoneFactory, TrumpetFactory\n",
    "    * Product\n",
    "        * ConcreteFactoryによって生成される側のオブジェクト\n",
    "        * ここではSaxophone, Trumpet"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       ":play"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# サックス (Product)\n",
    "class Saxophone\n",
    "  def initialize(name)\n",
    "    @name = name\n",
    "  end\n",
    "  \n",
    "  def play\n",
    "    puts \"#{@name} は音を奏でています\"\n",
    "  end\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       ":ship_out"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 楽器工場 (Creator)\n",
    "class InstrumentFactory\n",
    "  def initialize(number_saxophones)\n",
    "    @saxophones = []\n",
    "    number_saxophones.times do |i|\n",
    "      ### コンストラクタでサックスを作ると汎用的に使いまわせない！！\n",
    "      saxophone = Saxophone.new(\"サックス #{i}\")\n",
    "      @saxophones << saxophone\n",
    "    end\n",
    "  end\n",
    "  \n",
    "  # 楽器を出荷する\n",
    "  def ship_out\n",
    "    @tmp = @saxophones.dup\n",
    "    @saxophones = []\n",
    "    @tmp\n",
    "  end\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "サックス 0 は音を奏でています\n",
      "サックス 1 は音を奏でています\n",
      "サックス 2 は音を奏でています\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[#<Saxophone:0x007f0e76439f78 @name=\"\\u30B5\\u30C3\\u30AF\\u30B9 0\">, #<Saxophone:0x007f0e76439dc0 @name=\"\\u30B5\\u30C3\\u30AF\\u30B9 1\">, #<Saxophone:0x007f0e76439d20 @name=\"\\u30B5\\u30C3\\u30AF\\u30B9 2\">]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "factory = InstrumentFactory.new(3)\n",
    "saxophones = factory.ship_out\n",
    "saxophones.each { |saxophone| saxophone.play }"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 汎用的な形に修正"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       ":play"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# サックス (Product)\n",
    "class Saxophone\n",
    "  def initialize(name)\n",
    "    @name = name\n",
    "  end\n",
    "  \n",
    "  def play\n",
    "    ### サックスをProduct側に切り出し\n",
    "    puts \"サックス #{@name} は音を奏でています\"\n",
    "  end\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       ":play"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# トランペット (Product)\n",
    "class Trumpet\n",
    "  def initialize(name)\n",
    "    @name = name\n",
    "  end\n",
    "  \n",
    "  def play\n",
    "    puts \"トランペット #{@name} は音を奏でています\"\n",
    "  end\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       ":new_instrument"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 楽器工場 (Creator)\n",
    "class InstrumentFactory\n",
    "  def initialize(number_instruments)\n",
    "    @instruments = []\n",
    "    number_instruments.times do |i|\n",
    "      ### 楽器生成の処理を抽象化\n",
    "      instrument = new_instrument(\"楽器 #{i}\")\n",
    "      @instruments << instrument\n",
    "    end\n",
    "  end\n",
    "  \n",
    "  # 楽器を出荷する\n",
    "  def ship_out\n",
    "    tmp = @instruments.dup\n",
    "    @instruments = []\n",
    "    tmp\n",
    "  end\n",
    "end\n",
    "\n",
    "# SaxophoneFactory: サックスを生成する (ConcreteCreator)\n",
    "class SaxophoneFactory < InstrumentFactory\n",
    "  def new_instrument(name)\n",
    "    Saxophone.new(name)\n",
    "  end\n",
    "end\n",
    "\n",
    "# TrumpetFactory: トランペットを生成する (ConcreteCreator)\n",
    "class TrumpetFactory < InstrumentFactory\n",
    "  def new_instrument(name)\n",
    "    Trumpet.new(name)\n",
    "  end\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "サックス 楽器 0 は音を奏でています\n",
      "サックス 楽器 1 は音を奏でています\n",
      "サックス 楽器 2 は音を奏でています\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[#<Saxophone:0x007f0e76389d08 @name=\"\\u697D\\u5668 0\">, #<Saxophone:0x007f0e76389c68 @name=\"\\u697D\\u5668 1\">, #<Saxophone:0x007f0e76389bf0 @name=\"\\u697D\\u5668 2\">]"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "factory = SaxophoneFactory.new(3)\n",
    "saxophones = factory.ship_out\n",
    "saxophones.each{|saxophone| saxophone.play} "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "トランペット 楽器 0 は音を奏でています\n",
      "トランペット 楽器 1 は音を奏でています\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[#<Trumpet:0x007f0e76332120 @name=\"\\u697D\\u5668 0\">, #<Trumpet:0x007f0e763320a8 @name=\"\\u697D\\u5668 1\">]"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "factory = TrumpetFactory.new(2)\n",
    "trumpets = factory.ship_out\n",
    "trumpets.each{|trumpet| trumpet.play} "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Ruby 2.3.3",
   "language": "ruby",
   "name": "ruby"
  },
  "language_info": {
   "file_extension": ".rb",
   "mimetype": "application/x-ruby",
   "name": "ruby",
   "version": "2.3.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
